import axios, {AxiosError, type AxiosInstance, type AxiosResponse, type InternalAxiosRequestConfig} from 'axios'
import config from '@/config/axios/config'
import {isExternal, messageError} from '@/utils/commonUtil'
import {useUserStore} from '@/stores/modules/user.store'
import router from '@/router'
import {Local} from '@/utils/storageUtil'
import {cacheKeys} from '@/stores/constant/cacheKey'

const {base_url, request_timeout, authorization_header} = config

// 创建axios实例
const service: AxiosInstance = axios.create({
	baseURL: base_url, // api 的 base_url
	timeout: request_timeout, // 请求超时时间
	withCredentials: false // 禁用 Cookie 等信息
})

// request拦截器
service.interceptors.request.use(
		(config: InternalAxiosRequestConfig) => {
			const token = Local.get(cacheKeys.TOKEN)
			// 请求后端服务时携带token，请求外部接口时不携带token
			if (token && !isExternal(config.url)) {
				config.headers[authorization_header] = token
			}
			return config
		},
		(error: AxiosError) => {
			return Promise.reject(error)
		}
)

// response拦截器
service.interceptors.response.use(
		(response: AxiosResponse<any>) => {
			// 二进制数据则直接返回
			if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') {
				return response
			}
			// 后端返回的Result对象
			const result = response.data
			if (result.code !== 200) {
				// 未登录或token过期
				if (result.code === 401) {
					handle401()
				}
				const message = getErrorMessage(result?.code, result?.message)
				messageError(message)
				return Promise.reject(message)
			} else {
				return response
			}
		},
		(error: AxiosError) => {
			if (error.response) {
				const data = error.response.data as any
				// 外部接口返回的401不处理
				if (!isExternal(error.response.config.url) && (data?.code === 401 || error.response.status === 401)) {
					handle401()
				}
				const message = getErrorMessage(data?.code || error.response.status || error.code, data?.message || error.response.statusText || error.message)
				messageError(message)
			} else {
				messageError(getErrorMessage(error.code, error.message))
			}
			return Promise.reject(error)
		}
)

const getErrorMessage = (code?: string | number, msg?: string) => {
	if (code && msg) {
		return `${code}: ${msg}`
	} else if (code && !msg) {
		return `${code}`
	} else if (!code && msg) {
		return `${msg}`
	} else {
		return '错误'
	}
}

const handle401 = () => {
	useUserStore().clearAllUserInfo()
	let loginTo = router.currentRoute.value.path
	if (loginTo === '/login') {
		loginTo = '/'
	}
	router.push(`/login?loginTo=${loginTo}`).catch(() => {
	})
}

export default service
